#include"KeyRecommander.h"
#include<algorithm>
#include<iostream>

using std::cout;
using std::endl;

KeyRecommander::KeyRecommander(string &query )  //const TcpConnectionPtr &
:_queryWord(query)
,_1dict("./text1/")
{
    cout<<"KeyRecommander()"<<endl;
    _1dict.start();
    _dict=_1dict._dict;
    _1dict._dict.clear();
    _indexTable=_1dict._index;
    _1dict._index.clear();
}
KeyRecommander::~KeyRecommander(){
    cout<<"~KeyRecommander()"<<endl;
}

void KeyRecommander::execute(){ //执行查询
    cout<<"KeyRecommander::execute()"<<endl;
    queryIndexTable();
    statistic(_result);
    int i=0;
    for(auto it=_Myresult.begin();it!=_Myresult.end()&&i<10;it++){
        cout<<_dict[it->first].first<<endl;     //展示词频前10的单词
        i++;
    }
}                     
void KeyRecommander::queryIndexTable(){ //查询索引

    cout<<"KeyRecommander::queryIndexTable()"<<endl;
    //通过索引表找交集
    size_t len=_queryWord.size();
    if(len==1){
        _result=_indexTable[_queryWord[0]];
        return ;
    }
    size_t vecSize=_indexTable[_queryWord[0]].size();
    for(size_t i=1;i<len;i++){
        vecSize=std::max(_indexTable[_queryWord[i]].size(),vecSize);
    }

    vector<int>intersection(vecSize);       //设置交集
    auto iter=set_intersection(_indexTable[_queryWord[0]].begin(),_indexTable[_queryWord[0]].end(),
                     _indexTable[_queryWord[1]].begin(),_indexTable[_queryWord[1]].end(),
                     intersection.begin());
    intersection.resize(iter-intersection.begin());

    for(size_t i=2;i<_queryWord.size();i++){
        auto iter=set_intersection(_indexTable[_queryWord[i]].begin(),_indexTable[_queryWord[i]].end(),
                        intersection.begin(),intersection.end(),
                     intersection.begin());
        intersection.resize(iter-intersection.begin());
        //cout<<"第"<<i<<"次,交集大小"<<intersection.size()<<endl;
    }
    //此时索引全部存在intersection中
    //将结果保存到_result中 
    for(size_t i=0;i<intersection.size();i++){
        _result.insert(intersection[i]);
    }
    //cout<<intersection.size()<<endl;
    //cout<<_result.size()<<endl;

}             
void KeyRecommander::statistic(set<int>&iset){  //进行计算??重新排序？？
    cout<<"KeyRecommander::statistic()"<<endl;
    //只需要最多10个待选？ 
    //做最小编辑距离计算
    for(auto it=iset.begin();it!=iset.end();it++){
        int dis=distance(_dict[*it].first);
        _Myresult.push_back({*it,dis});       //第一个为词典下标，第二个为词频 
    }
    std::sort(_Myresult.begin(),_Myresult.end(),[](pair<int,int>a,pair<int,int>b){
    return a.second<b.second;});      //按照从大到小排列

    //for(auto it=_Myresult.begin();it!=_Myresult.end();it++){
    //    cout<<_dict[it->first].first<<" ";
    //}
}      
int KeyRecommander::distance(const string &rhs){    //计算最小编辑距离
    size_t lhs_len=length(_queryWord);
    size_t rhs_len=length(rhs);
    int editDist[lhs_len+1][rhs_len+1];
    for(size_t idx=0;idx<=lhs_len;++idx){
        editDist[idx][0]=idx;
    }

    for(size_t idx=0;idx<=rhs_len;++idx){
        editDist[0][idx]=idx;
    }

    string sublhs,subrhs;
    for(size_t dist_i=1,lhs_idx=0;dist_i<=lhs_len;++dist_i,++lhs_idx){
        size_t nBytes=nBytesCode(_queryWord[lhs_idx]);
        sublhs=_queryWord.substr(lhs_idx,nBytes);
        lhs_idx+=(nBytes-1);

        for(size_t dist_j=1,rhs_idx=0;dist_j<=rhs_len;++dist_j,++rhs_idx){
            nBytes=nBytesCode(rhs[rhs_idx]);
            subrhs=rhs.substr(rhs_idx,nBytes);
            rhs_idx+=(nBytes-1);
            if(sublhs==subrhs){
                editDist[dist_i][dist_j]=editDist[dist_i-1][dist_j-1];
            }else {
                editDist[dist_i][dist_j]=triple_min(editDist[dist_i][dist_j-1]+1,
                                                    editDist[dist_i-1][dist_j]+1,
                                                    editDist[dist_i-1][dist_j-1]+1);
            }
        }
    }
    return editDist[lhs_len][rhs_len];

}        

//void response();                  //响应客户的请求

size_t KeyRecommander::nBytesCode(const char ch){   //求取一个字符占据的字节数
    if(ch&(1<<7)){
        int nBytes=1;
        for(int idx=0;idx!=6;++idx){
            if(ch & (1<<(6-idx))){
                ++nBytes;
            }else 
                break;
        }
        return nBytes;
    }
    return 1;
}       
size_t KeyRecommander::length(const string &str){       //求取一个字符串的字符长度
    size_t ilen=0;
    for(size_t idx=0;idx!=str.size();++idx){
        int nBytes=nBytesCode(str[idx]);
        idx+=(nBytes-1);
        ++ilen;
    }
    return ilen;
}       
int KeyRecommander::triple_min(const int &a,const int &b,const int &c){
    return a<b?(a<c?a:c):(b<c?b:c);
}


